home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / python2.6 / dist-packages / PIL / OleFileIO.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  12.9 KB  |  412 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import string
  5. import StringIO
  6.  
  7. def i16(c, o = 0):
  8.     return ord(c[o]) + (ord(c[o + 1]) << 8)
  9.  
  10.  
  11. def i32(c, o = 0):
  12.     return ord(c[o]) + (ord(c[o + 1]) << 8) + (ord(c[o + 2]) << 16) + (ord(c[o + 3]) << 24)
  13.  
  14. MAGIC = '\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1'
  15. VT_EMPTY = 0
  16. VT_NULL = 1
  17. VT_I2 = 2
  18. VT_I4 = 3
  19. VT_R4 = 4
  20. VT_R8 = 5
  21. VT_CY = 6
  22. VT_DATE = 7
  23. VT_BSTR = 8
  24. VT_DISPATCH = 9
  25. VT_ERROR = 10
  26. VT_BOOL = 11
  27. VT_VARIANT = 12
  28. VT_UNKNOWN = 13
  29. VT_DECIMAL = 14
  30. VT_I1 = 16
  31. VT_UI1 = 17
  32. VT_UI2 = 18
  33. VT_UI4 = 19
  34. VT_I8 = 20
  35. VT_UI8 = 21
  36. VT_INT = 22
  37. VT_UINT = 23
  38. VT_VOID = 24
  39. VT_HRESULT = 25
  40. VT_PTR = 26
  41. VT_SAFEARRAY = 27
  42. VT_CARRAY = 28
  43. VT_USERDEFINED = 29
  44. VT_LPSTR = 30
  45. VT_LPWSTR = 31
  46. VT_FILETIME = 64
  47. VT_BLOB = 65
  48. VT_STREAM = 66
  49. VT_STORAGE = 67
  50. VT_STREAMED_OBJECT = 68
  51. VT_STORED_OBJECT = 69
  52. VT_BLOB_OBJECT = 70
  53. VT_CF = 71
  54. VT_CLSID = 72
  55. VT_VECTOR = 4096
  56. VT = { }
  57. for k, v in vars().items():
  58.     if k[:3] == 'VT_':
  59.         VT[v] = k
  60.     
  61.  
  62. WORD_CLSID = '00020900-0000-0000-C000-000000000046'
  63.  
  64. class _OleStream(StringIO.StringIO):
  65.     '''OLE2 Stream
  66.  
  67.     Returns a read-only file object which can be used to read
  68.     the contents of a OLE stream.  To open a stream, use the
  69.     openstream method in the OleFile class.
  70.  
  71.     This function can be used with either ordinary streams,
  72.     or ministreams, depending on the offset, sectorsize, and
  73.     fat table arguments.
  74.     '''
  75.     
  76.     def __init__(self, fp, sect, size, offset, sectorsize, fat):
  77.         data = []
  78.         while sect != -2:
  79.             fp.seek(offset + sectorsize * sect)
  80.             data.append(fp.read(sectorsize))
  81.             sect = fat[sect]
  82.         data = string.join(data, '')
  83.         StringIO.StringIO.__init__(self, data[:size])
  84.  
  85.  
  86.  
  87. class _OleDirectoryEntry:
  88.     '''OLE2 Directory Entry
  89.  
  90.     Encapsulates a stream directory entry.  Note that the
  91.     constructor builds a tree of all subentries, so we only
  92.     have to call it with the root object.
  93.     '''
  94.     
  95.     def __init__(self, sidlist, sid):
  96.         (name, type, sect, size, sids, clsid) = sidlist[sid]
  97.         self.sid = sid
  98.         self.name = name
  99.         self.type = type
  100.         self.sect = sect
  101.         self.size = size
  102.         self.clsid = clsid
  103.         self.kids = []
  104.         sid = sidlist[sid][4][2]
  105.         if sid != -1:
  106.             stack = [
  107.                 self.sid]
  108.             (left, right, child) = sidlist[sid][4]
  109.             while left != -1:
  110.                 stack.append(sid)
  111.                 sid = left
  112.                 (left, right, child) = sidlist[sid][4]
  113.             while sid != self.sid:
  114.                 self.kids.append(_OleDirectoryEntry(sidlist, sid))
  115.                 (left, right, child) = sidlist[sid][4]
  116.                 if right != -1:
  117.                     sid = right
  118.                     while None:
  119.                         (left, right, child) = sidlist[sid][4]
  120.                         if left == -1:
  121.                             break
  122.                         
  123.                         sid = left
  124.                         continue
  125.                         continue
  126.                         while None:
  127.                             ptr = stack[-1]
  128.                             del stack[-1]
  129.                             (left, right, child) = sidlist[ptr][4]
  130.                             if right != sid:
  131.                                 break
  132.                             
  133.                             sid = right
  134.                             continue
  135.                             (left, right, child) = sidlist[sid][4]
  136.                             if right != ptr:
  137.                                 sid = ptr
  138.                                 continue
  139.                     self.kids.sort()
  140.                 
  141.  
  142.     
  143.     def __cmp__(self, other):
  144.         '''Compare entries by name'''
  145.         return cmp(self.name, other.name)
  146.  
  147.     
  148.     def dump(self, tab = 0):
  149.         '''Dump this entry, and all its subentries (for debug purposes only)'''
  150.         TYPES = [
  151.             '(invalid)',
  152.             '(storage)',
  153.             '(stream)',
  154.             '(lockbytes)',
  155.             '(property)',
  156.             '(root)']
  157.         print ' ' * tab + repr(self.name), TYPES[self.type],
  158.         if self.type in (2, 5):
  159.             print self.size, 'bytes',
  160.         
  161.         print 
  162.         if self.type in (1, 5) and self.clsid:
  163.             print ' ' * tab + '{%s}' % self.clsid
  164.         
  165.         for kid in self.kids:
  166.             kid.dump(tab + 2)
  167.         
  168.  
  169.  
  170.  
  171. class OleFileIO:
  172.     '''OLE container object
  173.  
  174.     This class encapsulates the interface to an OLE 2 structured
  175.     storage file.  Use the listdir and openstream methods to access
  176.     the contents of this file.
  177.  
  178.     Object names are given as a list of strings, one for each subentry
  179.     level.  The root entry should be omitted.  For example, the following
  180.     code extracts all image streams from a Microsoft Image Composer file:
  181.  
  182.         ole = OleFileIO("fan.mic")
  183.  
  184.         for entry in ole.listdir():
  185.             if entry[1:2] == "Image":
  186.                 fin = ole.openstream(entry)
  187.                 fout = open(entry[0:1], "wb")
  188.                 while 1:
  189.                     s = fin.read(8192)
  190.                     if not s:
  191.                         break
  192.                     fout.write(s)
  193.  
  194.     You can use the viewer application provided with the Python Imaging
  195.     Library to view the resulting files (which happens to be standard
  196.     TIFF files).
  197.     '''
  198.     
  199.     def __init__(self, filename = None):
  200.         if filename:
  201.             self.open(filename)
  202.         
  203.  
  204.     
  205.     def open(self, filename):
  206.         '''Open an OLE2 file'''
  207.         if type(filename) == type(''):
  208.             self.fp = open(filename, 'rb')
  209.         else:
  210.             self.fp = filename
  211.         header = self.fp.read(512)
  212.         if len(header) != 512 or header[:8] != MAGIC:
  213.             raise IOError, 'not an OLE2 structured storage file'
  214.         header[:8] != MAGIC
  215.         clsid = self._clsid(header[8:24])
  216.         self.sectorsize = 1 << i16(header, 30)
  217.         self.minisectorsize = 1 << i16(header, 32)
  218.         self.minisectorcutoff = i32(header, 56)
  219.         self.loadfat(header)
  220.         self.loaddirectory(i32(header, 48))
  221.         self.ministream = None
  222.         self.minifatsect = i32(header, 60)
  223.  
  224.     
  225.     def loadfat(self, header):
  226.         sect = header[76:512]
  227.         fat = []
  228.         for i in range(0, len(sect), 4):
  229.             ix = i32(sect, i)
  230.             if ix == -2 or ix == -1:
  231.                 break
  232.             
  233.             s = self.getsect(ix)
  234.             fat = fat + map((lambda i, s = s: i32(s, i)), range(0, len(s), 4))
  235.         
  236.         self.fat = fat
  237.  
  238.     
  239.     def loadminifat(self):
  240.         s = self._open(self.minifatsect).read()
  241.         self.minifat = map((lambda i, s = s: i32(s, i)), range(0, len(s), 4))
  242.  
  243.     
  244.     def getsect(self, sect):
  245.         self.fp.seek(512 + self.sectorsize * sect)
  246.         return self.fp.read(self.sectorsize)
  247.  
  248.     
  249.     def _unicode(self, s):
  250.         return filter(ord, s)
  251.  
  252.     
  253.     def loaddirectory(self, sect):
  254.         fp = self._open(sect)
  255.         self.sidlist = []
  256.         while None:
  257.             entry = fp.read(128)
  258.             if not entry:
  259.                 break
  260.             
  261.             type = ord(entry[66])
  262.             name = self._unicode(entry[0:0 + i16(entry, 64)])
  263.             ptrs = (i32(entry, 68), i32(entry, 72), i32(entry, 76))
  264.             sect = i32(entry, 116)
  265.             size = i32(entry, 120)
  266.             clsid = self._clsid(entry[80:96])
  267.             continue
  268.             self.root = _OleDirectoryEntry(self.sidlist, 0)
  269.             return None
  270.  
  271.     
  272.     def dumpdirectory(self):
  273.         self.root.dump()
  274.  
  275.     
  276.     def _clsid(self, clsid):
  277.         if clsid == '\x00' * len(clsid):
  278.             return ''
  279.         return ('%08X-%04X-%04X-%02X%02X-' + '%02X' * 6) % ((i32(clsid, 0), i16(clsid, 4), i16(clsid, 6)) + tuple(map(ord, clsid[8:16])))
  280.  
  281.     
  282.     def _list(self, files, prefix, node):
  283.         prefix = prefix + [
  284.             node.name]
  285.         for entry in node.kids:
  286.             if entry.kids:
  287.                 self._list(files, prefix, entry)
  288.                 continue
  289.             files.append(prefix[1:] + [
  290.                 entry.name])
  291.         
  292.  
  293.     
  294.     def _find(self, filename):
  295.         node = self.root
  296.         for name in filename:
  297.             for kid in node.kids:
  298.                 if kid.name == name:
  299.                     break
  300.                     continue
  301.             else:
  302.                 raise IOError, 'file not found'
  303.             node = None
  304.         
  305.         return node.sid
  306.  
  307.     
  308.     def _open(self, start, size = 2147483647):
  309.         if size < self.minisectorcutoff:
  310.             if not self.ministream:
  311.                 self.loadminifat()
  312.                 self.ministream = self._open(self.sidlist[0][2])
  313.             
  314.             return _OleStream(self.ministream, start, size, 0, self.minisectorsize, self.minifat)
  315.         return _OleStream(self.fp, start, size, 512, self.sectorsize, self.fat)
  316.  
  317.     
  318.     def listdir(self):
  319.         '''Return a list of streams stored in this file'''
  320.         files = []
  321.         self._list(files, [], self.root)
  322.         return files
  323.  
  324.     
  325.     def openstream(self, filename):
  326.         '''Open a stream as a read-only file object'''
  327.         slot = self._find(filename)
  328.         (name, type, sect, size, sids, clsid) = self.sidlist[slot]
  329.         if type != 2:
  330.             raise IOError, 'this file is not a stream'
  331.         type != 2
  332.         return self._open(sect, size)
  333.  
  334.     
  335.     def getproperties(self, filename):
  336.         '''Return properties described in substream'''
  337.         fp = self.openstream(filename)
  338.         data = { }
  339.         s = fp.read(28)
  340.         clsid = self._clsid(s[8:24])
  341.         s = fp.read(20)
  342.         fmtid = self._clsid(s[:16])
  343.         fp.seek(i32(s, 16))
  344.         s = '****' + fp.read(i32(fp.read(4)) - 4)
  345.         for i in range(i32(s, 4)):
  346.             id = i32(s, 8 + i * 8)
  347.             offset = i32(s, 12 + i * 8)
  348.             type = i32(s, offset)
  349.             if type == VT_I2:
  350.                 value = i16(s, offset + 4)
  351.                 if value >= 32768:
  352.                     value = value - 65536
  353.                 
  354.             elif type == VT_UI2:
  355.                 value = i16(s, offset + 4)
  356.             elif type in (VT_I4, VT_ERROR):
  357.                 value = i32(s, offset + 4)
  358.             elif type == VT_UI4:
  359.                 value = i32(s, offset + 4)
  360.             elif type in (VT_BSTR, VT_LPSTR):
  361.                 count = i32(s, offset + 4)
  362.                 value = s[offset + 8:offset + 8 + count - 1]
  363.             elif type == VT_BLOB:
  364.                 count = i32(s, offset + 4)
  365.                 value = s[offset + 8:offset + 8 + count]
  366.             elif type == VT_LPWSTR:
  367.                 count = i32(s, offset + 4)
  368.                 value = self._unicode(s[offset + 8:offset + 8 + count * 2])
  369.             elif type == VT_FILETIME:
  370.                 value = long(i32(s, offset + 4)) + (long(i32(s, offset + 8)) << 32)
  371.                 value = value / 0x989680L
  372.             elif type == VT_UI1:
  373.                 value = ord(s[offset + 4])
  374.             elif type == VT_CLSID:
  375.                 value = self._clsid(s[offset + 4:offset + 20])
  376.             elif type == VT_CF:
  377.                 count = i32(s, offset + 4)
  378.                 value = s[offset + 8:offset + 8 + count]
  379.             else:
  380.                 value = None
  381.             data[id] = value
  382.         
  383.         return data
  384.  
  385.  
  386. if __name__ == '__main__':
  387.     import sys
  388.     for file in sys.argv[1:]:
  389.         
  390.         try:
  391.             ole = OleFileIO(file)
  392.             print '-' * 68
  393.             print file
  394.             print '-' * 68
  395.             ole.dumpdirectory()
  396.             for file in ole.listdir():
  397.                 if file[-1][0] == '\x05':
  398.                     print file
  399.                     props = ole.getproperties(file)
  400.                     props = props.items()
  401.                     props.sort()
  402.                     for k, v in props:
  403.                         print '   ', k, v
  404.                     
  405.                 
  406.         except IOError:
  407.             v = None
  408.             print '***', 'cannot read', file, '-', v
  409.  
  410.     
  411.  
  412.